package com.spyu.utils;

import org.springframework.beans.BeanUtils;
import java.io.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 对象拷贝工具类
 *
 * @author spyu
 * @date 2023-03-08
 */
public final class CopyUtils {

    /**
     * 深拷贝
     * @param source
     * @param <S>
     */
    public static <S extends Serializable, T extends Serializable> void copyBeanByDeep(S source, T dest) {
        ObjectOutputStream obs = null;
        ObjectInputStream os = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            obs = new ObjectOutputStream(out);
            obs.writeObject(source);
            //分配内存，写入原始对象，生成新对象
            ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray());
            os = new ObjectInputStream(is);
            S s = (S) os.readObject();
            BeanUtils.copyProperties(s, dest);
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (obs != null) {
                    obs.close();
                }

                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public static <S extends Serializable, T extends Serializable> List<T> copyListByDeep(List<S> sourceList, Class<T> clazz) {
        return sourceList.stream().map(source -> {
            T t = null;

            try {
                t = clazz.newInstance();
                copyBeanByDeep(source, t);
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }

            return t;
        }).collect(Collectors.toList());
    }

    /**
     * 浅拷贝对象
     * @param source
     * @param target
     * @param <S>
     * @param <T>
     */
    public static <S, T> void copyBeanByShallow(S source, T target) {
        BeanUtils.copyProperties(source, target);
    }

    /**
     * 浅拷贝集合
     * @param sourceList
     * @param clazz
     * @param <S>
     * @param <T>
     * @return
     */
    public static <S, T> List<T> copyListByShallow(List<S> sourceList, Class<T> clazz) {
        return sourceList.stream().map(source -> {
            T t = null;

            try {
                t = clazz.newInstance();
                copyBeanByShallow(source, t);
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }

            return t;
        }).collect(Collectors.toList());
    }

}
